//
//  LocationManager.swift
//  MetaU
//
//  Created by PerhapYs on 2022/4/12.
//

import Foundation
import CoreLocation
import UIKit

/// 需要在info.plist文件中添加
///
/*  <!-- 在使用期间访问位置 -->
<key>NSLocationWhenInUseUsageDescription</key>
<string>App需要您的同意,才能在使用期间访问位置</string>
 */

protocol LocationManager_h{
    
    /// 在获取授权后，请求地理位置
    /// - Parameter type: 获取的地理位置精度  kCLLocationAccuracyBest
    ///获取结果在requestSuccessBlock,requestFailBlock
    func requestLocation(type:CLLocationAccuracy)
    
    /// 请求位置成功回调
    var requestSuccessBlock : ReturnValueBlock<[CLLocation]>? {set get}
    
    /// 请求位置失败回调
    var requestFailBlock : ReturnValueBlock<Error>? {set get}
}
class LocationManager : NSObject{
    
    static var shared = LocationManager()
    
    lazy var manager: CLLocationManager = {
        let manager = CLLocationManager()
        manager.delegate = self
        return manager
    }()
    
    typealias AuthChangedBlock = EmptyCompleteBlock
    
    var authChangedBlock : AuthChangedBlock?
    
    var requestSuccessBlock : ReturnValueBlock<[CLLocation]>?
    var requestFailBlock : ReturnValueBlock<Error>?
    
    /// 获取位置授权
    /// - Parameter completeBlock: ~
    fileprivate func requestAuthorization(_ completeBlock:@escaping EmptyCompleteBlock){
        
        var locationStatus : CLAuthorizationStatus = .notDetermined
        if #available(iOS 14.0, *) {
            locationStatus = self.manager.authorizationStatus
        } else {
            locationStatus = CLLocationManager.authorizationStatus()
        }
        if locationStatus == .notDetermined{
            self.manager.requestWhenInUseAuthorization()
            self.authChangedBlock = completeBlock
        }
        else{
            completeBlock()
        }
    }
}
extension LocationManager : LocationManager_h{
    
    func requestLocation(type:CLLocationAccuracy){
        
        self.requestAuthorization {
            
            if CLLocationManager.locationServicesEnabled(){
                
                DispatchQueue.global().async {
                    //设置定位模式
                    self.manager.desiredAccuracy = type
                    // 发起获取位置
                    self.manager.requestLocation()
                }
            }
            else{
                debugPrint("无法获取定位")
            }
        }
    }
}
extension LocationManager : CLLocationManagerDelegate{
    
    /// 14.0以前,监听权限变动
    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        
        self.authChangedBlock?()
    }
    /// 14.0以后,监听权限变动
    func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
        
        self.authChangedBlock?()
    }
    ///返回定位的位置
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        guard !locations.isEmpty else {
            return
        }
        DispatchQueue.main.async {
            self.requestSuccessBlock?(locations)
        }
    }
    ///定位错误
    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        DispatchQueue.main.async {
            self.requestFailBlock?(error)
        }
    }
}

extension CLLocation{
    
    /// 地址反编码
    func reverseGeocode(_ successedBlock:@escaping ReturnValueBlock<Array<CLPlacemark>?>){
        
        let handler :(Array<CLPlacemark>?, Error?) -> () = { placeMarks , error  in
         
            guard error == nil else{
                debugPrint(error!.localizedDescription)
                return
            }

            successedBlock(placeMarks)
        }
        let geocoder = CLGeocoder()
        geocoder.reverseGeocodeLocation(self, completionHandler: handler)
    }
    //地址正编码
    class func geocodeAddress(_ address:String,successedBlock:@escaping ReturnValueBlock<Array<CLPlacemark>?>){
        
        let geoCoder = CLGeocoder()
        geoCoder.geocodeAddressString(address) { placeArr, error in
            
            guard error == nil else{
                debugPrint("正编码地址错误",error!)
                return
            }
            successedBlock(placeArr)
        }
    }
}
